package com.mad.base.objects.grid;

import java.util.ArrayList;

import com.mad.base.objects.GameObject;
import com.mad.base.system.EDirection;
import com.mad.base.system.ID;
import com.mad.base.system.IInit;
import com.mad.base.system.Range2D;

@SuppressWarnings( "unchecked" )
public class Grid extends GameObject implements IInit{

	private final int width, height; 
		
	private GridField[][] fields ; 
    private Range2D<ID> fieldRange ; 
	
	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

	public GridField getFieldByID(ID id){
	    if(this.fieldRange.isInRange( id ))
	        return this.fields[ID.convertX( id.getX() )][ID.convertY( id.getY() )] ; 
	    return null ; 
	}

	public ArrayList<ID> getFieldsByAttributes(EChangeableFieldAttribute fieldAttr){
	    return (fieldAttr == EChangeableFieldAttribute.COVERED) ? this.getCoveredFieldIDs() : this.getMarkedFieldIDs(); 
	}
	
	private ArrayList<ID> getCoveredFieldIDs(){
	    ArrayList<ID> res = new ArrayList<ID>(); 
	    for(GridField[] f1: this.fields) 
	        for(GridField f2: f1)
	            if(f2.getFieldCoverer().isCovered())
	                res.add( f2.getId() ); 
	    return res ; 
	}
	
	private ArrayList<ID> getMarkedFieldIDs(){
        ArrayList<ID> res = new ArrayList<ID>(); 
        for(GridField[] f1: this.fields) 
            for(GridField f2: f1)
                if(f2.getFieldMarker().isMarked())
                    res.add( f2.getId() ); 
        return res ; 
    }
	
	
	
	public Grid(int w, int h) {
		this.width = w ; 
		this.height = h ; 
		this.init(null); 
	}

    public boolean canAddShipToField(ID bowID, EDirection dir, int shipLength){
	    ID tmpRear = ID.calculateID( bowID, shipLength, dir );
	    return this.fieldRange.isInRange( bowID ) && this.fieldRange.isInRange( tmpRear ) ; 
	}

    public void addShipToField( ID bowID, EDirection dir, int shipLength )
    {
        switch ( dir )
        {
            case VERTICAL:
                for ( int y = ID.convertY( bowID.getY() ); y < ID.convertY( bowID.getY() ) + shipLength; y++ )
                    this.fields[ID.convertX( bowID.getX() )][y].getFieldCoverer().setCovered(true);
                break;
            case HORIZONTAL:
                for ( int x = ID.convertX( bowID.getX() ); x < ID.convertX( bowID.getX() )+ shipLength; x++ )
                    this.fields[x][ID.convertY( bowID.getY() )].getFieldCoverer().setCovered(true);
                break;
        }
    }
    
    public void setFieldCovered(ID id, boolean value){
        this.getFieldByID( id ).getFieldCoverer().setCovered(value);
    }
    
    public void setFieldMarked(ID id, boolean value){
        this.getFieldByID( id ).getFieldMarker().setMarked( true ); 
    }
    
    @Override
    public void init( Object o )
    {
        ID loID = null, hiID = null;
        this.fields = new GridField[this.width][this.height];
        for ( int x = 0; x < this.fields.length; x++ )
            for ( int y = 0; y < this.fields[x].length; y++ )
            {
                ID tmp = ID.getIDByCoords( x, y );
                if ( x <= 0 && y <= 0 )
                    loID = tmp;
                else if ( x >= this.fields.length - 1 && y >= this.fields[x].length - 1 )
                    hiID = tmp;
                this.fields[x][y] = new GridField( tmp );
            }
        this.fieldRange = new Range2D<ID>( loID, hiID );
        System.out.println(this.fieldRange);
	}
	
	@Override 
	public String toString() {
		String res = "" ; 
		for(int x=0; x<this.fields.length; x++){
			for(int y=0; y<this.fields[x].length; y++)
				res += " "+this.fields[x][y].getId()+" " ; 
			res += "\n" ;  
		}
		return res ; 
	}


}
